package com.cisco.videoscape.android.parsers.onnow;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Stack;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import com.cisco.videoscape.android.model.enums.DeviceTypeFlags;
import com.cisco.videoscape.android.model.onnow.Channel;
import com.cisco.videoscape.android.model.onnow.ChannelMetadata;
import com.cisco.videoscape.android.model.onnow.ChannelPhysicalAsset;
import com.cisco.videoscape.android.model.onnow.Image;
import com.cisco.videoscape.android.model.onnow.Station;
import com.cisco.videoscape.android.parsers.AbstractHandler;
import com.cisco.videoscape.android.util.DeviceTypeFlagHelper;

/**
 * Parser for Channels(getChannels/getChannel). Returns list of station objects
 * containing list of channels for getChannels call. 
 * @author aphadke
 *
 */
public class ChannelHandler extends AbstractHandler {

	private static final String TAG = "ChannelHandler";
	
	private boolean parseChannelDetails;
	
	private final Integer regionId;
	
	/** Parser objects**/
	private List<Station> stations;
	private Station station;
	private Channel channel;
	
	/**Station objects**/
	private Image image;
	
	/**Channel objects**/
	private String channelLabel;
	private String channelExtId;
	private String channelName;
	private Integer channelOrderNumber;
	private String bundleUuid;
	private ChannelMetadata channelMetadata;
	private ChannelPhysicalAsset channelPhysicalAsset;
	private String productUuid;
	private final static String EMPTY_STRING = "";
	
	private List<ChannelPhysicalAsset> channelPhysicalAssets;
	private EnumSet<DeviceTypeFlags> enumSetOfDeviceTypeFlags;
	
	public ChannelHandler(XMLReader reader, AbstractHandler handler, 
	        Stack<String> parentStack, Integer regionId) {
		super(reader, handler, parentStack);
		stations = new ArrayList<Station>(1);
		this.regionId = regionId;
	}

	@Override
	public void startElement(String uri, String localName, String name, 
	        Attributes attributes) throws SAXException {
		super.startElement(uri, localName, name, attributes);
		
		String path = getPath();		
//		Log.i(TAG,"Start Path is "+path);
		
//		Log.i(TAG,"Start Local name is "+localName);
		
		if(localName.equalsIgnoreCase("s")){
			station = new Station();
			channelLabel = EMPTY_STRING;
			channelExtId = EMPTY_STRING;
			channelName = EMPTY_STRING;
			channelOrderNumber = new Integer(0);
			bundleUuid = EMPTY_STRING;
			productUuid = EMPTY_STRING;
		} else if(localName.equalsIgnoreCase("cn")){
			channel = new Channel();
		} else if(localName.equalsIgnoreCase("i")){
			image = new Image();
			
			for (int i = 0; i < attributes.getLength(); i++){			
				String tmpAttributeValue = attributes.getValue(i);

				if((tmpAttributeValue != null) &&
					(tmpAttributeValue.length() == 0)){				
					continue;
				} else if(attributes.getLocalName(i).equalsIgnoreCase("h")) {
					image.setHeight(Integer.valueOf(tmpAttributeValue));
				} else if(attributes.getLocalName(i).equalsIgnoreCase("w")) {
					image.setWidth(Integer.valueOf(tmpAttributeValue));
				} else if(attributes.getLocalName(i).equalsIgnoreCase("p")) {
					image.setPrimary(Integer.valueOf(tmpAttributeValue));
				} else if(attributes.getLocalName(i).equalsIgnoreCase("d")) {
					image.setDefaultImage(Integer.valueOf(tmpAttributeValue));
				}
			}			
		} else if(localName.equalsIgnoreCase("bxml")){
			channelMetadata = new ChannelMetadata();
			channelPhysicalAssets = new ArrayList<ChannelPhysicalAsset>();
		}  else if(localName.equalsIgnoreCase("PhysicalAssetVideo") 
				|| localName.equalsIgnoreCase("PhysicalAssetManifest")) {
			channelPhysicalAsset = new ChannelPhysicalAsset();
			enumSetOfDeviceTypeFlags = EnumSet.noneOf(DeviceTypeFlags.class);
		}
	}

	@Override
	public void endElement(String uri, String localName, String name) 
	    throws SAXException {
		super.endElement(uri, localName, name);

		String path = getPath();
//		Log.i(TAG,"Process End Path is "+path);

		process(uri, localName, name, path, value);

		value = UNDEFINED;
	}

	private void process(String uri, String localName, String name, String path,
                         String value) {
		
//		Log.i(TAG,"Process Local name is "+localName);
		
		if(value !=null){
			value = value.trim();
		}
		
		if(localName.equalsIgnoreCase("s")){
			List<Channel> channels = station.getChannels();
			for(Channel ch: channels){
				ch.setChannelExtId(channelExtId);
				ch.setChannelLabel(channelLabel);
				ch.setChannelName(channelName);
				ch.setChannelOrderNumber(channelOrderNumber);
				ch.setBundleUuid(bundleUuid);
				ch.setChannelMetadata(channelMetadata);
				//ch.setChannelPhysicalAsset(channelPhysicalAsset);
				ch.setChannelPhysicalAssets(channelPhysicalAssets);
				ch.setProductUuid(productUuid);				
		}
			stations.add(station);
		} else if(localName.equalsIgnoreCase("seid")) {
			station.setStationExtId(value);			
		} else if(localName.equalsIgnoreCase("cs")){
			station.setCallSign(value);
		} else if(localName.equalsIgnoreCase("ceid")) {
			channelExtId = value ;
		} else if(localName.equalsIgnoreCase("n")) {
			channelName = value;
		} 
//		else if(localName.equalsIgnoreCase("cl")){
//			channelLabel = value;
//		} 
		else if(localName.equalsIgnoreCase("cord")){
			channelOrderNumber = Integer.valueOf(value);
		} else if(localName.equalsIgnoreCase("cn")){
			channel.setChannelNumber(Integer.valueOf(value));
			channel.setRegionId(regionId);			
			station.addChannel(channel);
		}  else if(localName.equalsIgnoreCase("i")){
			image.setUrl(value);
			station.addImage(image);
		}  else if(path.endsWith("/pxml/opencase/product") && 
				localName.equalsIgnoreCase("uuid")){
			productUuid = value;
		}  else if(path.endsWith("/pxml/opencase/product/bundle") && 
				localName.equalsIgnoreCase("name")){
			channelLabel = value;
		}
		//Only parse if it is a getChannel call
		if(parseChannelDetails){
			if (path.endsWith("/MetadataStation")){
				parseMetadata(uri, localName, name, value);
			} else if (path.endsWith("/Videos/PhysicalAssetVideo")
					||path.endsWith("/Videos/PhysicalAssetManifest")){
				parsePhysicalVideo(uri, localName, name, value);
			} else if(path.endsWith("/component")){
				if(localName.equalsIgnoreCase("uuid")){
					bundleUuid = value;
				}
			} else if ((path.endsWith("/Videos") 
					&& localName.equalsIgnoreCase("PhysicalAssetVideo")) 
					|| (path.endsWith("/Videos") 
					&& localName.equalsIgnoreCase("PhysicalAssetManifest"))){
				channelPhysicalAsset.setDeviceTypeFlags(DeviceTypeFlagHelper
						.getDeviceTypeFlagsValue(enumSetOfDeviceTypeFlags));
				channelPhysicalAssets.add(channelPhysicalAsset);
			} else if ((path.endsWith("/Videos/PhysicalAssetVideo/targetDevices/targetDevice")
					||	path.endsWith("/Videos/PhysicalAssetManifest/targetDevices/targetDevice"))) {
				if (value == null) {
					return;
				}
				
				if(localName.equalsIgnoreCase("type")){
					if (value.contains("type.mobile")) {
						enumSetOfDeviceTypeFlags.add(DeviceTypeFlags.MOBILE);
					} else if (value.contains("type.tablet")) {
						enumSetOfDeviceTypeFlags.add(DeviceTypeFlags.TABLET);
					} else if (value.contains("type.settop")) {
						enumSetOfDeviceTypeFlags.add(DeviceTypeFlags.SET_TOP);
					} else if (value.contains("type.tv")) {
						enumSetOfDeviceTypeFlags.add(DeviceTypeFlags.TV);
					} else if (value.contains("type.pc")) {
						enumSetOfDeviceTypeFlags.add(DeviceTypeFlags.PC);
					}
				} else if(localName.equalsIgnoreCase("os")){
					if (value.equalsIgnoreCase("android")) {
						enumSetOfDeviceTypeFlags.add(DeviceTypeFlags.ANDROID);
					} 
				}
			}
		}
	}
	
	private void parseMetadata(String uri, String localName, String name, String value){
		if(localName.equalsIgnoreCase("facebook")){
			channelMetadata.setFacebookUrl(value);
		}  else if(localName.equalsIgnoreCase("twitter")){
			channelMetadata.setTwitterUrl(value);
		} else if(localName.equalsIgnoreCase("website")){
			channelMetadata.setWebsiteUrl(value);
		} else if(localName.equalsIgnoreCase("summaryLong")){
			channelMetadata.setStationDescription(value);
		} else if(localName.equalsIgnoreCase("summaryShort")){
			channelMetadata.setStationDescription(value);
		} else if(localName.equalsIgnoreCase("summaryMedium")){
			channelMetadata.setStationDescription(value);
		} 
	}
	
	private void parsePhysicalVideo(String uri, String localName, String name, String value){
		if(localName.equalsIgnoreCase("url")){
			channelPhysicalAsset.setUrl(value);
		} else if(localName.equalsIgnoreCase("uuid")) {
			channelPhysicalAsset.setComponentUuid(value);
		} else if(localName.equalsIgnoreCase("isEncrypted")) {
			if (value != null) {
				value = value.trim();
			}
			channelPhysicalAsset.setEncrypted(Boolean.valueOf(value));
		} else if(localName.equalsIgnoreCase("pcFileName")) {
			channelPhysicalAsset.setPcFileName(value);
		} else if (localName.equalsIgnoreCase("isProgressive")) {
			if (value != null) {
				value = value.trim();
			}
			channelPhysicalAsset.setProgressive(Boolean.valueOf(value));
        } else if (localName.equalsIgnoreCase("deliveryType")) {
			channelPhysicalAsset.setDeliveryType(value);
        } else if (localName.equalsIgnoreCase("manifestType")) {
			channelPhysicalAsset.setDeliveryType(value);
        }
	}
	
	public void setParseChannelDetails(boolean parseChannelDetails) {
		this.parseChannelDetails = parseChannelDetails;
	}

	@Override
	public Object getReadObject() {
		if(parseChannelDetails){
			//return stations.get(0).getChannels().get(0);
			return stations.get(0);
		} else {
			return stations;
		}
	}


	public void setReader(XMLReader reader) {
		this.reader = reader;
	}

	/**
	 * Called by child handlers
	 */
	@Override
	public void callbackChildHandlerFinishedProcessing(AbstractHandler handler) {
		
	}
}
